﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Fiddler;

namespace BareWeb.HtmlExtension.Extensions
{
    public class HtmlInfoHelper
    {
        /// <summary>
        /// Determines whether the specified session is valid.
        /// </summary>
        /// <param name="session">The session.</param>
        public bool IsValid(Session session)
        {
            try
            {
                return session.oResponse.headers["Content-Type"].Contains("html") &&
                       session.GetResponseBodyAsString().Length > 0;
            }
            catch(Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Does the inspection.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <returns></returns>
        public HtmlInfo DoInspection(Session session)
        {
            return DoInspection(session.GetResponseBodyAsString());
        }
        public HtmlInfo DoInspection(string body)
        {
            HtmlInfo result = new HtmlInfo();

            double sum = 0D;
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(body);

            var elements = doc.DocumentNode.Descendants("input");
            if (elements.Any())
            {
                var viewState =
                    elements.FirstOrDefault(t => t.GetAttributeValue("name", string.Empty) == "__VIEWSTATE");
                if (viewState != null)
                {

                    result.ViewStateSize = viewState.GetAttributeValue("value", string.Empty).
                        Length;

                    sum += result.ViewStateSize;
                    DoLog("ViewState: {0}", result.ViewStateSize);
                }

                var nonViewState = elements.Where(t => t.GetAttributeValue("name", string.Empty) != "__VIEWSTATE");
                if (nonViewState.Any())
                {
                    result.FormElementsSize = nonViewState.Sum<HtmlAgilityPack.HtmlNode>(
                        t =>
                        t.GetAttributeValue("value", string.Empty).
                            Length);

                    sum += result.FormElementsSize;
                    DoLog("Form Elements: {0}", result.FormElementsSize);
                }
            }

            var longIdentifierNodes =
                doc.DocumentNode.Descendants().Where(
                    t =>
                    t.GetAttributeValue("id", string.Empty).Length > 10 &&
                    t.GetAttributeValue("id", string.Empty).Contains("_"));

            if (longIdentifierNodes != null && longIdentifierNodes.Any())
            {
                result.LongIdentifierSize = longIdentifierNodes.Sum<HtmlAgilityPack.HtmlNode>(
                    t =>
                    t.GetAttributeValue("id", string.Empty).
                        Length);
            }
            

            sum += result.LongIdentifierSize;
            DoLog("LongIdentifiers: {0}", result.LongIdentifierSize);

        


        var commentNodes = doc.DocumentNode.SelectNodes("//comment()");
            if (commentNodes != null && commentNodes.Any())
            {

                result.CommentsSize = commentNodes.Sum<HtmlAgilityPack.HtmlNode>(
                    t =>
                    t.OuterHtml.Length);


                sum += result.CommentsSize;
                DoLog("HTML Comments: {0}", result.CommentsSize);

            }

            var scriptImports =
                doc.DocumentNode.Descendants("script").Where(
                    t => t.GetAttributeValue("src", string.Empty) != string.Empty);
            if (scriptImports != null && scriptImports.Any())
            {
                result.ScriptImportsSize =
                    scriptImports.Sum<HtmlAgilityPack.HtmlNode>(
                        t =>
                        t.OuterHtml.Length);

                sum += result.ScriptImportsSize;
                DoLog("Script Imports: {0}", result.ScriptImportsSize);

            }

            var headerElement = doc.DocumentNode.Descendants("head").FirstOrDefault();
            if (headerElement != null)
            {
                result.HeadSize = headerElement.OuterHtml.Length;

                sum += result.HeadSize;
                DoLog("<head> : {0}", result.HeadSize);
            }

            var whitespaceRough = Regex.Replace(body, @"\s+", " ").Trim();
            var whitespaceCalc = body.Length - whitespaceRough.Length;
            sum += whitespaceCalc;

            result.WhitespaceSize = whitespaceCalc;
            DoLog("Whitespace: {0}", whitespaceCalc);

            result.RemainingBodySize = body.Length - sum;

            DoLog("Content: {0}", result.RemainingBodySize);

            return result;
        }

        public void DoLog(string format, params object[] args)
        {
            FiddlerApplication.Log.LogString(string.Format(format, args));
        }  

    }
}
